import {ComponentFactoryResolver, Directive, EventEmitter, Input, OnChanges, SimpleChange, SimpleChanges, Type, ViewContainerRef} from '@angular/core';
import {hasOwnProperty} from 'tslint/lib/utils';
import {DynamicComponent} from '../components/dynamic-component/dynamic-component.interface';

/**
 * 这个指令用于动态创建组件
 * @deprecated 推荐使用动态组件 {@link DynamicComponentComponent} 而不是这个指令
 * */
@Directive({
  selector: '[ngToolsDynamicComponent]'
})
export class DynamicComponentDirective implements OnChanges {
  private options;
  private component: Type<DynamicComponent>;
  private firstChange = true;
  private componentChanged = true;
  private instance;
  events: EventEmitter<any>[];


  @Input() set ngToolsDynamicComponent(value: { component: Type<DynamicComponent>; options: any }) {
    this.options = value.options;
    this.component = value.component;
  }

  constructor(private viewContainer: ViewContainerRef, private componentFactoryResolver: ComponentFactoryResolver) {
  }

  createComponent() {
    const componentFactory = this.componentFactoryResolver.resolveComponentFactory(this.component);
    this.viewContainer.clear();
    const componentRef = this.viewContainer.createComponent(componentFactory);
    return <DynamicComponent>componentRef.instance;
  }

  applyChanges() {
    if (this.componentChanged) {
      this.instance = this.createComponent();
      if (hasOwnProperty(this.instance, 'dynamicComponentEvent')) {
        this.instance['dynamicComponentEvent'].subscribe((e) => {
        });
      }
      for (const propName of this.instance) {
        if (this.instance[propName] instanceof EventEmitter) {
          this.instance[propName].subscribe((e) => {
            const evt = new EventEmitter<any>();
            evt.emit(e);
            this.events.push(evt);
          });
        }
      }
    }
    this.instance.options = this.options;
    const changes = {
      options: new SimpleChange(null, this.options, this.firstChange)
    };
    if ('ngOnChanges' in this.instance) {
      this.instance['ngOnChanges'](changes);
    }
  }

  ngOnChanges(changes: SimpleChanges): void {
    if (changes.ngToolsDynamicComponent) {
      if (changes.ngToolsDynamicComponent.previousValue) {
        this.componentChanged = changes.ngToolsDynamicComponent.previousValue.component !== changes.ngToolsDynamicComponent.currentValue.component;
      } else {
        this.componentChanged = true;
      }
      this.applyChanges();
      this.firstChange = false;
    }
  }

}
